package com.um.jdy.mp.order.manager;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.um.jdy.common.base.enums.YesOrNo;
import com.um.jdy.common.charge.code.OrderCode;
import com.um.jdy.common.charge.entity.po.*;
import com.um.jdy.common.charge.entity.vo.EbOrderVO;
import com.um.jdy.common.charge.entity.vo.EboxOrderVO;
import com.um.jdy.common.charge.entity.vo.EvOrderVO;
import com.um.jdy.common.charge.entity.vo.OrderEnergyVO;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.charge.service.*;
import com.um.jdy.common.commons.service.StatusService;
import com.um.jdy.common.device.entity.po.Station;
import com.um.jdy.common.device.service.StationService;
import com.um.jdy.common.member.enums.MemberEnum;
import com.um.jdy.common.member.enums.PayEnum;
import com.um.jdy.common.system.entity.po.Param;
import com.um.jdy.common.system.service.ParamService;
import com.um.jdy.mp.order.entity.vo.StationOrderSummaryItemVO;
import com.um.jdy.mp.order.entity.vo.*;
import com.um.jdy.mp.user.service.SessionUserService;
import com.um.jdy.rpc.enums.DeviceTypeEnum;
import com.um.springboot.starter.entity.Page;
import com.um.springboot.starter.orm.entity.Response;
import com.um.springboot.starter.orm.manager.BaseManager;
import com.um.springboot.starter.utils.StringUtil;
import com.um.springboot.starter.utils.UMBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
@Slf4j
public class ChargeOrderManager extends BaseManager<OrderService> {

    @Autowired
    SessionUserService sessionUserService;

    @Autowired
    EbOrderService ebOrderService;

    @Autowired
    EvOrderService evOrderService;

    @Autowired
    EboxOrderService eboxOrderService;

    @Autowired
    OrderService orderService;

    @Autowired
    PbOrderService pbOrderService;

    @Autowired
    StatusService statusService;

    @Autowired
    ParamService paramService;

    @Autowired
    StationService stationService;

    @Autowired
    OrderPlaceService orderPlaceService;

    @Autowired
    OrderEnergyService orderEnergyService;

    /**
     * 分页查询订单
     * @return
     */
    public Response<Page<OrderItemVO>> page(Integer pageNo,Integer pageSize,String orderStatus,String orderNo) {
        Page<OrderItemVO> page = new Page<>();
        page.setPageNo(pageNo);
        page.setPageSize(pageSize);

        String status = "%";
        String payStatus = "%";

        if (!orderStatus.equals(OrderEnum.OrderStatus.All.name())) {
            if(orderStatus.equals(OrderEnum.OrderStatus.Doing.name())){
                status = OrderEnum.Status.Charging.name();
            }else if(orderStatus.equals(OrderEnum.OrderStatus.UnPay.name())){
                payStatus = PayEnum.Status.UnPayed.name();
                status = OrderEnum.Status.Completed.name();
            }else if(orderStatus.equals(OrderEnum.OrderStatus.Completed.name())){
                status = OrderEnum.Status.Completed.name();
                payStatus = PayEnum.Status.Payed.name();
            }

        }

        page = service.getViewModelPageBySqlName(page, "get_charge_order_page", "get_charge_order_count",OrderItemVO.class,
                new Object[]{getComId(),sessionUserService.getTokenUserId(),status,payStatus,StringUtil.getQueryParam(orderNo)});

        page.getResult().stream().forEach(orderItem -> {
            orderItem.setOrderStatus(statusService.getOrderStatus(orderItem.getChargeOrderId(),orderItem.getStatus(),orderItem.getPayStatus(),orderItem.getDeviceType()));

            if(DeviceTypeEnum.EV.name().equals(orderItem.getDeviceType())){
                if(OrderEnum.OrderStatus.Place == orderItem.getOrderStatus()){
                    this.calcEVOrderPlaceFee(orderItem);
                }

                // TODO 订单列表免费订单不显示订单金额，订单详情要显示，后面可能会改
                if(YesOrNo.Yes.name().equals(orderItem.getIsFree())){
                    orderItem.setOrderAmount(0);
                }
            } else  if(DeviceTypeEnum.EB.name().equals(orderItem.getDeviceType())) {
                EbOrder ebOrder = ebOrderService.getEntity("charge_order_id", orderItem.getChargeOrderId());
                if(ebOrder != null) {
                    if (orderItem.getOrderStatus() == OrderEnum.OrderStatus.Doing  && StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        ebOrder.setServiceFee(orderService.getServiceFee(orderItem.getChargeOrderId()));
                        ebOrder.setEnergyFee(orderService.getEnergyFee(orderItem.getChargeOrderId()));

                        orderItem.setChargeAmount(ebOrder.getServiceFee() + ebOrder.getEnergyFee());
                        orderItem.setOrderAmount(orderItem.getChargeAmount());
                    }
                }
            }
        });
        return Response.success(page);
    }

    public Response<OrderDetailVO> get(String id) {
        OrderDetailVO orderVO = service.getViewModel("get_charge_order_info", OrderDetailVO.class,
                new Object[]{id, sessionUserService.getTokenUserId(),service.getComId()});
        if(orderVO == null)
            return Response.failed(OrderCode.NoOrder);

        orderVO.setOrderStatus(statusService.getOrderStatus(orderVO.getChargeOrderId(),orderVO.getStatus(),orderVO.getPayStatus(),orderVO.getDeviceType()));

        switch (DeviceTypeEnum.valueOf(orderVO.getDeviceType())){
            case EB:
                EbOrder ebOrder = ebOrderService.getEntity("charge_order_id", orderVO.getChargeOrderId());
                if(ebOrder != null) {
                    if (orderVO.getOrderStatus() == OrderEnum.OrderStatus.Doing  && StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        ebOrder.setServiceFee(orderService.getServiceFee(orderVO.getChargeOrderId()));
                        ebOrder.setEnergyFee(orderService.getEnergyFee(orderVO.getChargeOrderId()));

                        ebOrder.setChargeCapacity(orderService.getCapacity(orderVO.getChargeOrderId()));

                        orderVO.setChargeAmount(ebOrder.getServiceFee() + ebOrder.getEnergyFee());
                        orderVO.setOrderAmount(orderVO.getChargeAmount());
                    }

                    if (StringUtil.equals(ebOrder.getFeeType(), OrderEnum.FeeType.Energy.name())) {
                        orderVO.setEbEnergyList(orderService.getOrderFeeList(orderVO.getChargeOrderId()));
                    }

                    orderVO.setEbOrder(UMBeanUtils.copyBean(ebOrder, EbOrderVO.class));
                }
                break;
            case EV:
                EvOrder evOrder = (evOrderService.getEntity("charge_order_id",orderVO.getChargeOrderId()));
                if(evOrder != null)
                    orderVO.setEvOrder(UMBeanUtils.copyBean(evOrder,EvOrderVO.class));
                break;
            case EBox:
                EboxOrder eboxOrder = eboxOrderService.getEntity("charge_order_id",orderVO.getChargeOrderId());
                if(eboxOrder != null)
                    orderVO.setEboxOrder(UMBeanUtils.copyBean(eboxOrder,EboxOrderVO.class));
                break;
            case PB:
                PbOrderDetailVO pbOrderDetail = pbOrderService.getViewModel("get_pb_order_detail",PbOrderDetailVO.class,new Object[]{orderVO.getChargeOrderId(),getComId()});
                if(pbOrderDetail != null) {
                    orderVO.setPbOrder(pbOrderDetail);
                }
                break;
        }

        //设置订单标说明
        if(orderVO.getOrderStatus() == OrderEnum.OrderStatus.Doing){
            orderVO.setExplain("正在充电中");
        }else if(orderVO.getOrderStatus() == OrderEnum.OrderStatus.Completed){
            Param param = paramService.getEntity(new String[]{"path","p_key"},new Object[]{"order.explain."+orderVO.getDeviceType(),orderVO.getEndType()});
            if(param != null){
                orderVO.setExplain(param.getPValue());
            }else{
                orderVO.setExplain("您的订单已完成！");
            }
        }else if(orderVO.getOrderStatus() == OrderEnum.OrderStatus.Place){
            orderVO.setExplain("正在占位计费中");
            if (orderVO.getDeviceType().equals(DeviceTypeEnum.EV.name())) {

                calcEVOrderPlaceFee(orderVO);
            }
        }else if(orderVO.getOrderStatus() == OrderEnum.OrderStatus.UnPay){
            orderVO.setExplain("你的订单还没有付款，请尽快支付哟");
        }

        return Response.success(orderVO);
    }


    /**
     * 网点订单统计累计数据
     * @return
     */
    public StationOrderSummaryVO getStationOrderSummary(){
        String accountId = sessionUserService.getTokenUserId();
        String datetime = DateUtil.format(new Date(),"yyyy-MM-dd")+" 23:59:59";
        if(sessionUserService.getTokenUser().getType().equals(MemberEnum.UserType.merchant.name())) {
            StationOrderSummaryVO stationOrderSummaryVO = service.getViewModel("get_merchant_station_order_summary", StationOrderSummaryVO.class, new Object[]{datetime, accountId});
            return stationOrderSummaryVO;
        }else{
            StationOrderSummaryVO stationOrderSummaryVO = service.getViewModel("get_sharing_station_order_summary", StationOrderSummaryVO.class, new Object[]{datetime, accountId});
            return stationOrderSummaryVO;
        }
    }

    /**
     * 网点订单统计
     * @return
     */
    public StationOrderSummaryListVO getStationOrderSummaryList(String id, String type, String year_or_month) {

        String accountId = sessionUserService.getTokenUserId();
        List<StationOrderSummaryItemVO> list = new ArrayList<>();
        int totalOrders = 0;
        int totalCommission = 0;

        if (id.isEmpty()) {//统计网点列表
            String begin = "";
            String end = "";

            if (type.equals("year")) {
                begin = year_or_month + "-01-01 00:00:00";//2023-01-01 00:00:00
                end = year_or_month + "-12-31 23:59:59";//2023-12-31 23:59:59
            } else if (type.equals("month")) {
                String[] arr = StringUtils.split(year_or_month,"-");
                int days = com.um.springboot.starter.utils.DateUtil.checkMonth(StringUtil.toInt(arr[1]),StringUtil.toInt(arr[0]));
                begin = year_or_month + "-01 00:00:00";//2023-01-01 00:00:00
                end = year_or_month + "-" + days + " 23:59:59";//2023-12-31 23:59:59
            }

            if(sessionUserService.getTokenUser().getType().equals(MemberEnum.UserType.merchant.name())) {
                list = service.getViewModelList("get_merchant_station_order_summary_list", StationOrderSummaryItemVO.class, new Object[]{begin, end, accountId});
            }else{
                list = service.getViewModelList("get_sharing_station_order_summary_list", StationOrderSummaryItemVO.class, new Object[]{begin, end, accountId});
            }
            for (StationOrderSummaryItemVO stationItem : list) {
                totalOrders += StringUtil.toInt(stationItem.getOrderNum());
                totalCommission += StringUtil.toInt(stationItem.getCommission());
            }

        } else {//统计网点详情

            if(type.equals("year")){
                List<StationOrderSummaryItemVO> orders = service.getViewModelList("get_station_order_summary_by_year", StationOrderSummaryItemVO.class,new Object[]{year_or_month, id});

                for(int index = 1;index <= 12;index ++){
                    String month = year_or_month.trim()+"-"+(index < 10 ? "0"+index : index);

                    StationOrderSummaryItemVO item = new StationOrderSummaryItemVO();
                    item.setMonthOrDate(month);
                    item.setCommission(0);
                    item.setOrderNum(0);

                    for(StationOrderSummaryItemVO orderItem : orders){
                        if(orderItem.getMonthOrDate().equals(month)){
                            item.setOrderNum(orderItem.getOrderNum());
                            item.setCommission(orderItem.getCommission());
                            totalOrders += StringUtil.toInt(orderItem.getOrderNum());
                            totalCommission += StringUtil.toInt(orderItem.getCommission());
                            break;
                        }
                    }

                    list.add(item);
                }
            }else if(type.equals("month")){
                List<StationOrderSummaryItemVO> orders = service.getViewModelList("get_station_order_summary_by_month", StationOrderSummaryItemVO.class,new Object[]{year_or_month, id});

                String[] arr = StringUtils.split(year_or_month,"-");
                int days = com.um.springboot.starter.utils.DateUtil.checkMonth(StringUtil.toInt(arr[1]),StringUtil.toInt(arr[0]));
                for(int index = 1;index <= days;index ++){
                    String date = year_or_month.trim()+"-"+(index < 10 ? "0"+index : index);

                    StationOrderSummaryItemVO item = new StationOrderSummaryItemVO();
                    item.setMonthOrDate(date);
                    item.setCommission(0);
                    item.setOrderNum(0);

                    for(StationOrderSummaryItemVO orderItem : orders){
                        if(orderItem.getMonthOrDate().equals(date)){
                            item.setOrderNum(orderItem.getOrderNum());
                            item.setCommission(orderItem.getCommission());
                            totalOrders += orderItem.getOrderNum();
                            totalCommission += StringUtil.toInt(orderItem.getCommission());
                            break;
                        }
                    }

                    list.add(item);
                }
            }

        }

        StationOrderSummaryListVO summaryVO = new StationOrderSummaryListVO();
        summaryVO.setCommission(totalCommission);
        summaryVO.setOrderNum(totalOrders);
        summaryVO.setList(list);

        if (!id.isEmpty()) {
            Station station = stationService.getEntity(id);
            if(station != null){
                summaryVO.setName(station.getName());
                summaryVO.setLogo(station.getThumb());
            }
        }

        return summaryVO;
    }

    private void calcEVOrderPlaceFee(OrderDetailVO order){
        OrderPlace orderPlace = orderPlaceService.getRow("charge_order_id", order.getChargeOrderId());
        if(null != orderPlace){
            order.getEvOrder().setPlaceEndTime(DateUtil.date());
            long between = DateUtil.between(order.getEvOrder().getPlaceBeginTime(), order.getEvOrder().getPlaceEndTime(), DateUnit.SECOND);
            order.getEvOrder().setPlaceSeconds((int) Math.max(0, between - orderPlace.getFreeDuration() * 60));

            if (orderPlace.getStatus().equals(YesOrNo.Yes.name()) && order.getEvOrder().getPlaceSeconds() > 0) {//收占位费
                order.getEvOrder().setPlaceAmount(evOrderService.savePlaceFee(orderPlace, BeanUtil.toBean(order.getEvOrder(), EvOrder.class), false));
            }

            order.setOrderAmount(order.getOrderAmount() + order.getEvOrder().getPlaceAmount());
        }
    }

    private void calcEVOrderPlaceFee(OrderItemVO order){
        OrderPlace orderPlace = orderPlaceService.getRow("charge_order_id", order.getChargeOrderId());
        if(null != orderPlace){

            EvOrder evOrder = (evOrderService.getEntity("charge_order_id",order.getChargeOrderId()));

            evOrder.setPlaceEndTime(DateUtil.date());
            long between = DateUtil.between(evOrder.getPlaceBeginTime(), evOrder.getPlaceEndTime(), DateUnit.SECOND);
            evOrder.setPlaceSeconds((int) Math.max(0, between - orderPlace.getFreeDuration() * 60));

            if (orderPlace.getStatus().equals(YesOrNo.Yes.name()) && evOrder.getPlaceSeconds() > 0) {//收占位费
                evOrder.setPlaceAmount(evOrderService.savePlaceFee(orderPlace, evOrder, false));
            }

            order.setOrderAmount(order.getOrderAmount() + evOrder.getPlaceAmount());
        }
    }
}
